Willy Tarreau [Wed, 11 Aug 2021 09:12:46 +0000 (11:12 +0200)]
BUG/MAJOR: h2: enforce checks on the method syntax before translating to HTX
The situation with message components in H2 is always troubling. They're
produced by the HPACK layer which contains a dictionary of well-known
hardcoded values, yet wants to remain binary transparent and protocol-
agnostic with HTTP just being one user, yet at the H2 layer we're
supposed to enforce some checks on some selected pseudo-headers that
come from internal constants... The :method pseudo-header is no exception
and is not tested when coming from the HPACK layer. This makes it possible
to pass random chars into methods, that can be serialized on another H2
connection (where they would not harm), or worse, on an H1 connection
where they can be used to transform the forwareded request. This is
similar to the request line injection described here:
https://portswigger.net/research/http2
A workaround here is to reject malformed methods by placing this rule
in the frontend or backend, at least before leaving haproxy in H1:
http-request reject if { method -m reg [^A-Z0-9] }
Alternately H2 may be globally disabled by commenting out the "alpn"
directive on "bind" lines, and by rejecting H2 streams creation by
adding the following statement to the global section:
tune.h2.max-concurrent-streams 0
This patch adds a check for each character of the method to be part of
the ones permitted in a token, as mentioned in RFC7231#4.1. This should
be backported to versions 2.0 and above, maybe even 1.8. For older
versions not having HTX_FL_PARSING_ERROR, a "goto fail" works as well
as it results in a protocol error at the stream level. Non-HTX versions
were initially thought to be safe but must be carefully rechecked since
they transcode the request into H1 before processing it.
Willy Tarreau [Tue, 10 Aug 2021 14:30:55 +0000 (16:30 +0200)]
BUG/MAJOR: h2: verify that :path starts with a '/' before concatenating it
Tim Düsterhus found that while the H2 path is checked for non-emptiness,
invalid chars and '*', a test is missing to verify that except for '*',
it always starts with exactly one '/'. During the reconstruction of the
full URI when passing to HTX, this allows to affect the apparent authority
by appending a port number or a suffix name.
This only affects H2-to-H2 communications, as H2-to-H1 do not use the
authority. Like for previous fix, the following rule installed in the
frontend or backend is sufficient to renormalize the internal URI:
http-request set-header host %[req.hdr(host)]
This needs to be backported to 2.2, since earlier versions do not rebuild
a full URI using the authority and will fail on the malformed path at the
HTTP layer.
Willy Tarreau [Tue, 10 Aug 2021 13:37:34 +0000 (15:37 +0200)]
BUG/MAJOR: h2: verify early that non-http/https schemes match the valid syntax
While we do explicitly check for strict character sets in the scheme,
this is only done when extracting URL components from an assembled one,
and we have special handling for "http" and "https" schemes directly in
the H2-to-HTX conversion. Sadly, this lets all other ones pass through
if they start exactly with "http://" or "https://", allowing the
reconstructed URI to start with a different looking authority if it was
part of the scheme.
It's interesting to note that in this case the valid authority is in
the Host hedaer and that the request will only be wrong if emitted over
H2 on the backend side, since H1 will not emit an absolute URI by
default and will drop the scheme. So in essence, this is a variant of
the scheme-based attack described below in that it only affects H2-H2
and not H2-H1 forwarding:
https://portswigger.net/research/http2
As such, a simple workaround consists in just adding the following
rule in the frontend or backend, which will have for effect to
renormalize the authority in the request line according to the
concatenated version:
http-request set-uri %[url]
This patch simply adds the missing syntax checks for non-http/https
schemes before the concatenation in the H2 code. An improvement may
consist in the future in splitting these ones apart in the start
line so that only the "url" sample fetch function requires to access
them together and that all other places continue to access them
separately. This will then allow the core code to perform such checks
itself.
The patch needs to be backported as far as 2.2. Before 2.2 the full
URI was not being reconstructed so the scheme and authority part were
always dropped from H2 requests to leave only origin requests. Note
for backporters: this depends on this previous patch:
MINOR: http: add a new function http_validate_scheme() to validate a scheme
Many thanks to Tim Düsterhus for figuring that one and providing a
reproducer.
Willy Tarreau [Tue, 10 Aug 2021 13:35:36 +0000 (15:35 +0200)]
MINOR: http: add a new function http_validate_scheme() to validate a scheme
While http_parse_scheme() extracts a scheme from a URI by extracting
exactly the valid characters and stopping on delimiters, this new
function performs the same on a fixed-size string.
[PATCH] BUG/MINOR: tcpcheck: Update .health threshold of agent inside an agent-check
If an agent-check is configured for a server, When the response is parsed,
the .health threshold of the agent must be updated on up/down/stopped/fail
command and not the threshold of the health-check. Otherwise, the
agent-check will compete with the health-check and may mark a DOWN server as
UP.
This patch should fix the issue #1176. It must be backported as far as 2.2.
(cherry picked from commit 24ec9434271345857b42cc5bd9c6b497ab01a7e4) Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 789bbdc88d7ffe8f520532efb18148ea52ede4ca) Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
Gbp-Pq: Name 0001-BUG-MINOR-tcpcheck-Update-.health-threshold-of-agent.patch
As HAProxy is running chrooted by default, we rely on an additional syslog
socket created by rsyslog inside the chroot for logging. As this socket cannot
trigger syslog activation, we explicitly order HAProxy after rsyslog.service.
Note that we are not using syslog.service here, since the additional socket is
rsyslog-specific.
Forwarded: no
Last-Update: 2017-12-01
Gbp-Pq: Name haproxy.service-start-after-syslog.patch
* Non-maintainer upload by the Security Team.
* BUG/MEDIUM: mux-h2: Refuse interim responses with end-stream flag set
(CVE-2023-0056)
* BUG/CRITICAL: http: properly reject empty http header field names
(CVE-2023-25725)